package org.erp.procurement.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.erp.common.constant.Constants;
import org.erp.common.page.PageQueryModel;
import org.erp.procurement.convert.MiniOrderConvert;
import org.erp.procurement.entity.MiniOrder;
import org.erp.procurement.entity.OrderProductDetails;
import org.erp.procurement.entity.ProcurementPayment;
import org.erp.procurement.entity.bo.MiniOrderAddBo;
import org.erp.procurement.entity.bo.MiniOrderConfirmBo;
import org.erp.procurement.entity.bo.OrderProductDetailsAddBo;
import org.erp.procurement.entity.bo.OrderUpdateBo;
import org.erp.procurement.entity.dto.MiniOrderQueryDto;
import org.erp.procurement.entity.vo.MiniOrderVo;
import org.erp.procurement.enums.OrderEventEnum;
import org.erp.procurement.enums.PaymentStatusEnum;
import org.erp.procurement.exception.ProcurementException;
import org.erp.procurement.mapper.MiniOrderMapper;
import org.erp.procurement.service.MiniOrderService;
import org.erp.procurement.service.OrderProductDetailsService;
import org.erp.procurement.service.OrderStateMachineService;
import org.erp.procurement.service.ProcurementPaymentService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @author libin
 * @version 1.0
 * @description:
 * @date 2025/11/5 11:06
 **/
@Log4j2
@Service
@AllArgsConstructor
public class MiniOrderServiceImpl extends ServiceImpl<MiniOrderMapper, MiniOrder> implements MiniOrderService {

    private final MiniOrderConvert miniOrderConvert;

    private final OrderProductDetailsService orderProductDetailsService;

    private final OrderStateMachineService orderStateMachineService;

    private final ProcurementPaymentService procurementPaymentService;

    @Override
    public PageQueryModel<MiniOrderVo> miniPageList(MiniOrderQueryDto miniOrderQueryDto) {
        Page<MiniOrder> page = this.page(miniOrderQueryDto.buildPage()
                , new QueryWrapper<MiniOrder>().lambda()
                        .like(StringUtils.isNotBlank(miniOrderQueryDto.getOrderNo()), MiniOrder::getOrderNo, miniOrderQueryDto.getOrderNo())
                        .like(StringUtils.isNotBlank(miniOrderQueryDto.getSellName()), MiniOrder::getSellName, miniOrderQueryDto.getSellName())
                        .like(StringUtils.isNotBlank(miniOrderQueryDto.getTrackingNumber()), MiniOrder::getTrackingNumber, miniOrderQueryDto.getTrackingNumber())
                        .eq(null != miniOrderQueryDto.getTenantId(), MiniOrder::getTenantId, miniOrderQueryDto.getTenantId())
                        .eq(null != miniOrderQueryDto.getStoreId(), MiniOrder::getStoreId, miniOrderQueryDto.getStoreId())
                        .eq(null != miniOrderQueryDto.getStatus(), MiniOrder::getStatus, miniOrderQueryDto.getStatus())
                        .ge(null != miniOrderQueryDto.getStartTime(), MiniOrder::getCreateTime, miniOrderQueryDto.getStartTime())
                        .le(null != miniOrderQueryDto.getEndTime(), MiniOrder::getCreateTime, miniOrderQueryDto.getEndTime()));
        return PageQueryModel.of(page.getPages(), page.getRecords().stream()
                .map(miniOrderConvert::convertVo).toList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void miniSave(MiniOrderAddBo miniOrderAddBo) {
        MiniOrder miniOrder = MiniOrder.addBuild(miniOrderAddBo);
        this.save(miniOrder);
        //todo 获取租户id,name
        if (1 == miniOrder.getPurchaseQuantity()) {
            OrderProductDetails orderProductDetails = OrderProductDetails.addOneBuild(miniOrder.getOrderNo(), miniOrderAddBo);
            orderProductDetailsService.save(orderProductDetails);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void miniConfirmReceipt(MiniOrderConfirmBo miniOrderConfirmBo) {
        //获取当前采购订单及详情信息
        MiniOrder miniOrder = this.getOne(new QueryWrapper<MiniOrder>().lambda()
                .eq(MiniOrder::getOrderNo, miniOrderConfirmBo.getOrderNo()));
        if (ObjectUtils.isEmpty(miniOrder)) {
            throw new ProcurementException("线上采购订单不存在");
        }
        OrderProductDetails orderProductDetails = orderProductDetailsService.getOne(new QueryWrapper<OrderProductDetails>().lambda()
                .eq(OrderProductDetails::getOrderNo, miniOrderConfirmBo.getOrderNo()));
        //判断详情信息是否存在
        if (ObjectUtils.isNotEmpty(orderProductDetails)) {
            OrderProductDetailsAddBo orderProductDetailsAddBo = miniOrderConfirmBo.getOrderProductDetailsAddBoList().get(0);
            orderProductDetailsService.buildParam(orderProductDetailsAddBo, orderProductDetails);
            miniOrder.setRecycleAmount(orderProductDetails.getRecycleAmount());
            orderProductDetailsService.updateById(orderProductDetails);
        } else {
            List<OrderProductDetails> orderProductDetailsList = orderProductDetailsService.buildOrderProductDetailsList(miniOrderConfirmBo.getOrderProductDetailsAddBoList(), miniOrderConfirmBo.getOrderNo());
            miniOrder.setRecycleAmount(orderProductDetailsList.stream().mapToInt(OrderProductDetails::getRecycleAmount).sum());
            orderProductDetailsService.saveBatch(orderProductDetailsList);
        }
        this.updateById(miniOrder);
        //更改状态
        boolean process = orderStateMachineService.process(miniOrder.getOrderNo(), OrderEventEnum.CONFIRM_RECEIPT);
        if (!process) {
            throw new ProcurementException("更新状态失败,请稍后再试");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void miniQuote(String orderNo) {
        MiniOrder miniOrder = this.getOne(new QueryWrapper<MiniOrder>().lambda()
                .eq(MiniOrder::getOrderNo, orderNo));
        if (ObjectUtils.isEmpty(miniOrder)) {
            throw new ProcurementException("线上采购订单不存在");
        }
        List<OrderProductDetails> list = orderProductDetailsService.list(new QueryWrapper<OrderProductDetails>().lambda()
                .eq(OrderProductDetails::getOrderNo, orderNo));
        miniOrder.setRecycleAmount(list.stream().mapToInt(OrderProductDetails::getRecycleAmount).sum());
        miniOrder.setRecycleQuantity(list.stream().filter(o -> 0 != o.getRecycleAmount()).toList().size());
        miniOrder.setReturnQuantity(list.size() - miniOrder.getReturnQuantity());
        updateById(miniOrder);
        boolean process = orderStateMachineService.process(orderNo, OrderEventEnum.CONFIRM_QUOTE);
        if (!process) {
            throw new ProcurementException("更新状态失败,请稍后再试");
        }
    }

    @Override
    public void updatePurchaseQuantity(OrderUpdateBo orderUpdateBo) {
        MiniOrder miniOrder = this.getOne(new QueryWrapper<MiniOrder>().lambda()
                .eq(MiniOrder::getOrderNo, orderUpdateBo.getOrderNo()));
        if (ObjectUtils.isEmpty(miniOrder)) {
            throw new ProcurementException("线上采购订单不存在");
        }
        miniOrder.setPurchaseQuantity(orderUpdateBo.getPurchaseQuantity());
        this.updateById(miniOrder);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void miniCancel(String orderNo) {
        boolean process = orderStateMachineService.process(orderNo, OrderEventEnum.CANCEL);
        if (!process) {
            throw new ProcurementException("更新状态失败,请稍后再试");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void miniConfirm(String orderNo) {
        MiniOrder miniOrder = this.getOne(new QueryWrapper<MiniOrder>().lambda()
                .eq(MiniOrder::getOrderNo, orderNo));
        if (ObjectUtils.isEmpty(miniOrder)) {
            throw new ProcurementException("线上采购订单不存在");
        }
        ProcurementPayment procurementPayment = new ProcurementPayment();
        procurementPayment.setPaymentNo(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())
                + String.valueOf(Math.random()).substring(2, 6));
        procurementPayment.setOrderNo(orderNo);
        procurementPayment.setSellId(miniOrder.getSellId());
        procurementPayment.setTenantId(miniOrder.getTenantId());
        procurementPayment.setAmount(miniOrder.getRecycleAmount());
        procurementPayment.setChannel(1);
        procurementPayment.setStatus(PaymentStatusEnum.TO_BE_PAID.getCode());
        procurementPaymentService.save(procurementPayment);
        try {
            //todo 调用财务模块获取订单状态
            if (Constants.SUCCESS.equals(200)) {
                procurementPayment.setStatus(PaymentStatusEnum.SUCCESS.getCode());
            } else {
                procurementPayment.setStatus(PaymentStatusEnum.FAILED.getCode());
                procurementPayment.setFailedMessage("业务异常");
            }
        } catch (Exception e) {
            procurementPayment.setStatus(PaymentStatusEnum.FAILED.getCode());
            procurementPayment.setFailedMessage("系统调用异常");
            log.error("调用财务模块失败", e);
        }
        procurementPaymentService.updateById(procurementPayment);
        if (PaymentStatusEnum.SUCCESS.getCode().equals(procurementPayment.getStatus())) {
            boolean process = orderStateMachineService.process(orderNo, OrderEventEnum.FINISH);
            if (!process) {
                throw new ProcurementException("更新状态失败,请稍后再试");
            }
        }
    }
}
